package com.zhdl.modules.demo.task;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.project.common.util.DelayUtil;
import com.zhdl.common.eventbus.center.EventBusCenter;
import com.zhdl.common.util.WebResult;
import com.zhdl.hardware.motor.buke.repository.impl.BukePortCmdHandle;
import com.zhdl.hardware_modules.service.DeviceService;
import com.zhdl.modules.autopick.NewCameraProcessWest;
import com.zhdl.modules.autopick.NewProcessControl;
import com.zhdl.modules.autopick.ProcessControl;
import com.zhdl.modules.autopick.entity.CameraCoordinate;
import com.zhdl.modules.autopick.entity.WestData;
import com.zhdl.modules.autopick.repository.CameraRepository;
import com.zhdl.modules.autopick.service.CameraService;
import com.zhdl.modules.autopick.service.CmdHandleService;
import com.zhdl.modules.autopick.web.response.NewMemDevice;
import com.zhdl.modules.autopick.web.service.DogfoodingService;
import com.zhdl.modules.eastdosing.NewCameraProcess;
import com.zhdl.modules.slagRemoval.SlagRemovalProcess;
import com.zhdl.modules.tools.EventBusTag;
import com.zhdl.network.service.impl.RobotArmServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.Arrays;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import static com.zhdl.modules.autopick.ProcessControl.isTest;

@Slf4j
@RestController
@RequestMapping(path = "/api/demo", produces = MediaType.APPLICATION_JSON_VALUE)
public class DemoController {

    private static final ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
    private final Map<Integer, SseEmitter> sseEmitters = new ConcurrentHashMap<>();
    private long sseSeq;
    @Autowired
    public ThreadPoolTaskScheduler taskScheduler1;
    @Autowired
    public CmdHandleService cmdHandleService;
    @Autowired
    public CameraService cameraService;
    @Resource
    DeviceService deviceService;
    @Autowired
    private ProcessControl processControl;
    @Autowired
    private DogfoodingService dogfoodingService;

    @Resource
    private SlagRemovalProcess slagRemovalProcess;
    @Resource
    private CameraRepository cameraRepository;
    /**
     * Modbus TCP  02 功能码 读取一组开关输入的当前状态（ON/OFF）
     * 读5个输入状态
     * （10001=1、10002=0、10003=1、10004=0、10005=1）
     * （15=0001 0101）提示15为十六进制数。
     * 发送：00 00 00 00 00 06 01 02 00 00 00 05
     * 00 01 00 00 00 06 65 02 00 00 00 30
     * 接收：00 00 00 00 00 04 01 02 01 15
     * 00 01 00 00 00 09 01 02 06 01 00 01 00 00 01
     * <p>
     * Modbus TCP  01 功能码 读取一组逻辑线圈的当前状态（ON/OFF）
     * 读5个线圈状态：（00001=1、00002=1、00003=1、00004=1、00005=1）
     * 返回状态：（1F=0001 1111）
     * 发送：00 00 00 00 00 06 01 01 00 00 00 05
     * 00 01 00 00 00 06 65 01 00 00 00 10
     * 接收：00 00 00 00 00 04 01 01 01 1F
     * 00 01 00 00 00 05 01 01 02 01 00
     */

    /*
        ----------------------------APP测试接口-远程IO-----------------------------
     */


    /*
        ----------------------------APP测试接口-步科电机-----------------------------
     */

//    /**
//     * 东区电机移动-电机运动
//     */
//    @GetMapping("/motorEasternRun")
//    public WebResult<String> motorEasternRun(int destinationValue, int tSpeedValue) {
//        //控制东区电机移动
//        cmdHandleService.motorEasternRun(1, 1);
//        return WebResult.okResult("Eastern motor already run : move distance is " + destinationValue + " pulse, speed is " + tSpeedValue + " , success!");
//    }
//
//    /**
//     * 东区电机移动-电机运动
//     */
//    @GetMapping("/motorEasternStop")
//    public WebResult<String> motorEasternStop() {
//        //控制东区电机-停止运动
//        cmdHandleService.motorEasternStop();
//        return WebResult.okResult("Eastern motor already stop success!");
//    }

    @Resource
    private BukePortCmdHandle bukePortCmdHandle;

    @GetMapping("/westData")
    public WebResult<String> westData() {
        WestData westData = processControl.westData;
        String content = "";
        content += westData.getRobotDataOne() + ",";
        content += westData.getRobotDataTwo() + ",";
        content += westData.getRobotDataThree() + ",";
        content += westData.getRobotDataFour();
        return WebResult.okResult(content);
    }

    /*
        ----------------------------APP测试接口-机器人-----------------------------
     */

    /**
     * 内部测试-电机-初始化
     */
    @GetMapping("/robotInit")
    public WebResult<String> robotInit() {
        EventBusTag eventBusTag = new EventBusTag();
        eventBusTag.setTag("robotInit");
        EventBusCenter.getEventBus().post(eventBusTag);
        return WebResult.okResult("readOriginDistance success!");
    }

    /**
     * 内部测试-电机-抓取
     */
    @GetMapping("/robotPick")
    public WebResult<String> robotPick() {
        EventBusTag eventBusTag = new EventBusTag();
        eventBusTag.setTag("robotPick");
        EventBusCenter.getEventBus().post(eventBusTag);
        return WebResult.okResult("readOriginDistance success!");
    }

    /**
     * 内部测试-电机-读取电机坐标
     */
    @GetMapping("/motorPosition")
    public WebResult<String> motorPosition() {
        EventBusTag eventBusTag = new EventBusTag();
        eventBusTag.setTag("motorLocation");
        EventBusCenter.getEventBus().post(eventBusTag);
        return WebResult.okResult("readOriginDistance success!");
    }

    /**
     * 内部测试-IO-Io读写
     */
    @GetMapping("/ioWrite")
    public WebResult<String> ioWriteDoubleCoil() {
        cmdHandleService.motorOpenFunnel();
        return WebResult.okResult("readOriginDistance success!");
    }

    /**
     * 内部测试-电机-电机运动到传感器Id的位置
     */
    @GetMapping("/motorRun4")
    public WebResult<String> motorRun4(int id) {
        int sensorId = idToSensorId(id);
        if (isTest == 1) {
            processControl.processEntryBySensorId(sensorId);
            return WebResult.okResult("move success!");
        } else {
            return WebResult.failResult("move fail!");
        }
    }

    /**
     * 流程 - 设置调试模式
     */
    @GetMapping("/processStart")
    public WebResult<String> processStart(boolean open) {
        /* 0为自动 1为手动 */
        if (open) {
            isTest = 1;
            deviceService.setProcessMode(isTest);

        } else {
            isTest = 0;
            deviceService.setProcessMode(isTest);
        }
        processControl.sseResp.setProcessMode(isTest);
        return WebResult.okResult("Process set up: " + open + " success!");
    }

    public int idToSensorId(int id) {
        if (id == 1) {
            return 8;
        } else if (id == 2) {
            return 14;
        } else if (id == 3) {
            return 20;
        } else if (id == 4) {
            return 26;
        }
        return 999;
    }

    /**
     * 创建SSE长链接
     *
     * @param clientId 客户端唯一ID(如果为空，则由后端生成并返回给前端)
     * @return org.springframework.web.servlet.mvc.method.annotation.SseEmitter
     **/
    @GetMapping("/CreateSseConnect")
    public SseEmitter createSseConnect(@RequestParam(name = "clientId", required = false) String clientId) {
        return dogfoodingService.createSseConnect(clientId);
    }

    /**
     * 关闭SSE连接
     *
     * @param clientId 客户端ID
     * @author re
     * @date 2021/12/13
     **/
    @GetMapping("/CloseSseConnect")
    public WebResult<String> closeSseConnect(String clientId) {
        dogfoodingService.closeSseConnect(clientId);
        return WebResult.okResult("true");
    }

    @GetMapping("/cameraC")
    public WebResult<String> cameraC() {
        log.info(String.valueOf(System.currentTimeMillis()));
        cameraService.getComputeResult();
        log.info(String.valueOf(System.currentTimeMillis()));
        return WebResult.okResult("Process set up:  success!");
    }

    /**
     * 机器人流程 - 设置Z轴高度
     */
    @GetMapping("/robotSetAxisZ")
    public WebResult<String> robotSetAxisZ(int locationZ) {
        // originZ = locationZ;
//        slagRemovalProcess.processAutomaticMode();
        return WebResult.okResult("Robot Z-axis set up: " + locationZ + "success!");
    }

    /**
     * 机器人流程 - 设置Z轴高度
     */
    @GetMapping("/robotXStart")
    public WebResult<String> robotXStart() {
        processControl.processEntryByCassetteId(1);
        return WebResult.okResult("Robot Z-axis set up: " + "success!");
    }

    /**
     * 机器人流程 - 设置UVW轴高度
     */
    @GetMapping("/robotSetAxisUVW")
    public WebResult<String> robotSetAxisZ(int locationU, int locationV, int locationW) {
        int[] locationUVW = {locationU, locationV, locationW};
        RobotArmServiceImpl.UVW = locationUVW;
        return WebResult.okResult("Robot Z-axis set up: " + Arrays.toString(locationUVW) + "success!");
    }

    /**
     * 机器人流程 - 抓料点位置
     */
    @GetMapping("/robotPickLocation")
    public WebResult<String> robotPickLocation(int locationX, int locationY, int locationZ) {
        //获取机器人需要走动的坐标
        int[] location = {locationX, locationY, locationZ};
        cmdHandleService.pickLocation(location);
        int[] locationUp = {locationX, locationY, locationZ};
        cmdHandleService.pickUpLocation(locationUp);
        return WebResult.okResult("Robot pick location set up: " + Arrays.toString(location) + "success!");
    }

    /**
     * 机器人流程 - 抓料点正上方位置
     */
    @GetMapping("/robotPickUpLocation")
    public WebResult<String> robotPickUpLocation(int locationX, int locationY, int locationZ) {
        //获取机器人需要走动的坐标
        int[] location = {locationX, locationY, locationZ};
        cmdHandleService.pickUpLocation(location);
        return WebResult.okResult("Robot pickUp location set up: " + Arrays.toString(location) + "success!");
    }

    /**
     * 机器人流程 - 初始化位置
     */
    @GetMapping("/robotInitLocation")
    public WebResult<String> robotInitLocation(int locationX, int locationY, int locationZ) {
        //获取机器人需要走动的坐标
        int[] location = {locationX, locationY, locationZ};
        cmdHandleService.robotSetZLocation(location);
        return WebResult.okResult("Robot init location set up: " + Arrays.toString(location) + "success!");
    }

    /**
     * 机器人流程 - 信号交互
     */
    @GetMapping("/robotSendM00")
    public WebResult<String> robotSendM00(int robotStatusM) {
        //获取地址，直接发送指令
        cmdHandleService.robotSendM(robotStatusM, true);
        return WebResult.okResult("Send robot signal : " + robotStatusM + "success!");
    }

    /**
     * 清除数据库信息
     */
    @GetMapping("/clearCamera")
    public WebResult<String> clearCamera(int florNum) {
        florNum = 9 -florNum;
        Optional<CameraCoordinate> byId = cameraRepository.findById(1);
        CameraCoordinate coordinate = byId.get();
        coordinate.setCameraParam("");
        coordinate.setFlorNum(florNum);
        coordinate.setBagNum(0);
        cameraRepository.save(coordinate);

        ProcessControl.orationType = -1;
        processControl.release();
        return WebResult.okResult("clear mysql success!");
    }


    /**
     * 机器人流程 - 信号交互
     */
//    @GetMapping("/robotReceiveM00")
//    public WebResult<String> robotReceiveM00(@RequestParam(name = "robotStatusM") Integer robotStatusM) {
//        if (robotStatusM != null) {
//        // 获取地址，使用后清除
//            cmdHandleService.robotReceiveM(robotStatusM, false);
//            return WebResult.okResult("Receive robot signal : " + robotStatusM + " success!");
//        } else {
//            return WebResult.okResult("Robot status not provided.");
//        }
//    }

    /*
        ----------------------------APP测试接口-机器人结束-----------------------------
     */

    /*
        ----------------------------APP测试接口-汇川电机-----------------------------
     */




    /*
        ----------------------------APP测试接口-汇川电机结束-----------------------------
     */

    /*
        ----------------------------APP测试接口-远程IO-----------------------------
     */

    /**
     * 机器人流程 - 信号交互
     */
    @GetMapping("/robotPause")
    public WebResult<String> robotSetPause(boolean open) {
        //获取地址，直接发送指令
        cmdHandleService.robotSetPause(open);
        return WebResult.okResult("robot already pause status:" + open);
    }

    /**
     * 机器人流程 - 信号交互
     */
    @GetMapping("/robotReceiveM00")
    public WebResult<String> robotReceiveM00(int robotStatusM) {
        //获取地址，使用后清除
        cmdHandleService.robotReceiveM(robotStatusM, false);
        return WebResult.okResult("Receive robot signal : " + robotStatusM + "success!");
    }

    /**
     * 电机流程 - 电机运动
     */
    @GetMapping("/motorRunDistance")
    public WebResult<String> motorRunDistance(int motorDistance, int motorSpeed) {
        //开始的时候，先让电机停止使能
        cmdHandleService.motorStop();
        //设置运行需要的速度 -默认 第0到第1端运行
        cmdHandleService.motorRun("110C", motorDistance);
        cmdHandleService.motorRunSpeed(motorSpeed);
        //运动使能 17
        DelayUtil.delayedExecution(1000, new Runnable() {
            @Override
            public void run() {
                cmdHandleService.motorReadyAndRun();
            }
        });
        return WebResult.okResult("Process motor run : " + motorDistance + "success!");
    }

    /**
     * 电机流程 - 电机停止运动
     *
     * @return
     */
    @GetMapping("/motorStop")
    public WebResult<String> motorStop() {
        //电机停止运动
        cmdHandleService.motorStop();
        return WebResult.okResult("Motor already stop!");
    }

    @GetMapping("/testProcess")
    public WebResult<String> testProcess() {
        //电机停止运动
        processControl.testProcess();
        return WebResult.okResult("Process already run!");
    }

    /**
     * 首页数据请求
     */
    @GetMapping(value = "/sse/{id}", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public SseEmitter handleSse(@PathVariable Integer id) {
        log.info(id.toString());
        SseEmitter emitter = new SseEmitter();
        sseEmitters.put(id, emitter);
        // 超时移除
        emitter.onTimeout(() -> {
            emitter.complete();
            sseEmitters.remove(id);
        });
        // 完成移除
        emitter.onCompletion(() -> sseEmitters.remove(id));
        // 每一秒发送一条消息
        executorService.scheduleAtFixedRate(() -> {
            ObjectMapper mapper = new ObjectMapper();

            //加载内存数据
            WebResult<NewMemDevice> sseResp = WebResult.okResult(processControl.newNemDevice);
            try {
                emitter.send(SseEmitter.event().id(String.valueOf(getSseSeq())).data(mapper.writeValueAsString(sseResp), MediaType.APPLICATION_JSON));
                log.info("send" + sseResp);
            } catch (IOException e) {
                emitter.complete();
            }
        }, 0, 1, TimeUnit.SECONDS);

        return emitter;
    }

    /**
     * 获取SSE序号
     */
    private long getSseSeq() {
        if (sseSeq > 65535L * 65535)
            sseSeq = 0;
        return sseSeq++;
    }

    /**
     * Modbus TCP  05功能码 强置一个逻辑线圈的通断状态
     * 发送：00 00 00 00 00 06 01 05 00 00 FF 00
     * 接收：00 00 00 00 00 06 01 05 00 00 FF 00
     *
     * @param address 地址
     * @param open    打开状态
     */
    @GetMapping("/ioWriteCoil")
    public WebResult<String> ioWriteCoil(int address, int open) {
        if (open == 1) {
            String booleanStr = "FF00";
            //写入io信号
            cmdHandleService.ioWriteCoil(address, booleanStr);
        } else if (open == 0) {
            String booleanStr = "0000";
            //写入io信号
            cmdHandleService.ioWriteCoil(address, booleanStr);
        } else {
            return WebResult.okResult("你输入的状态值不对");
        }

        return WebResult.okResult("IO write address is" + address + ", value is" + open + "success!");
    }

    /**
     * 东区电机移动-电机运动
     */
    @GetMapping("/motorEasternRun")
    public WebResult<String> motorEasternRun(String id, int destinationValue, int tSpeedValue) {
        //控制东区电机移动
        bukePortCmdHandle.bukeMotorRun("2", id, destinationValue, tSpeedValue);
        return WebResult.okResult("Eastern motor already run : move distance is " + destinationValue + " pulse, speed is " + tSpeedValue + " , success!");
    }

    /**
     * 东区电机移动-电机运动
     */
    @GetMapping("/motorEasternStop")
    public WebResult<String> motorEasternStop(String id) {
        //控制东区电机-停止运动
        bukePortCmdHandle.bukeMotorNoReady("2", id);
        return WebResult.okResult("Eastern motor already stop success!");
    }

    /*
        ----------------------------APP测试接口-步科电机结束-----------------------------
     */

        /*
        ----------------------------APP测试接口-汇川电机-----------------------------
     */

    /**
     * 电机流程-找原点
     */
    @GetMapping("/motorGoHome")
    public WebResult<String> motorGoHome() {
        //控制电机-使能
        cmdHandleService.motorReady();
        //控制电机-开始找原点
        cmdHandleService.motorGoHome();
        return WebResult.okResult("motor already init success!");
    }

    /**
     * 电机流程 - 电机运动
     */
    @GetMapping("/motorSlagRun")
    public WebResult<String> motorSlagRunDistance(String motorId, int motorDistance, int motorSpeed) {
        //开始的时候，先让电机停止使能
        cmdHandleService.motorSlagStop(motorId);
        //设置运行需要的速度 -默认 第0到第1端运行
        cmdHandleService.motorSlagRun(motorId, "110C", motorDistance);
        cmdHandleService.motorSlagRunSpeed(motorId, motorSpeed);
        //运动使能 17
        DelayUtil.delayedExecution(1000, new Runnable() {
            @Override
            public void run() {
                cmdHandleService.motorReadyAndRun();
            }
        });
        return WebResult.okResult("Process motor run : " + motorDistance + "success!");
    }

    /**
     * 电机流程 - 电机停止运动
     */
    @GetMapping("/motorSlagStop")
    public WebResult<String> motorSlagStop(String motorId) {
        //电机停止运动
        cmdHandleService.motorSlagStop(motorId);
        return WebResult.okResult("Motor already stop!");
    }

    /*
        ----------------------------APP测试接口-汇川电机结束-----------------------------
     */
    @GetMapping("/portDemo")
    public WebResult<String> comPortDemo() {
        //cmdHandleService.motorSlagStop("01");
        cmdHandleService.motorSlagRun("01", "110C", 100);
        //cmdHandleService.motorSlagRunSpeed("01",100);
        return WebResult.okResult("Motor read success!");
    }


    /*
        控制相机拍照
     */
    @GetMapping("/takePhoto")
    public WebResult<String> takePhoto() {
        cameraService.takePhoto();
        return WebResult.okResult("Motor read success!");
    }

    @Resource
    NewCameraProcessWest newCameraProcesswe;
    @Resource
    NewProcessControl newProcessControl;
    @GetMapping("/startCamera")
    public WebResult<String> startCamera() {
        newCameraProcesswe.startCamera();
        return WebResult.okResult("Eastern startCamera success!");
    }
    @GetMapping("/commonTest/{test}")
    public WebResult<String> commonTest(@PathVariable int test) {
        if (test == 0){
            newCameraProcesswe.startCamera();
        }else if (test == 1){
            newProcessControl.initRobot();
        }else if (test == 2){
            newProcessControl.reStart();
        } else if (test == 3) {
            newProcessControl.stopProcess();
        }

        return WebResult.okResult(test+"test!");
    }
}
